package priv.lhy.security.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;

/**
 * @author: lihy
 * date: 2019/11/15 11:11
 * description:
 */
@Configuration
//@EnableWebSecurity    //springboot可自动装配，可以不写
//@EnableGlobalMethodSecurity(prePostEnabled=true)   //开启方法级别的保护
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Qualifier("databaseUserService")
    @Autowired
    private UserDetailsService userDetailsService;

    /**
     * 配置用户信息服务,用户信息保存在内存中
     * @return
     */
    /*@Bean
    @Override
    public UserDetailsService userDetailsService() {
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();

        manager.createUser(User.withUsername("admin").password(passwordEncoder.encode("123")).authorities("p1").build());
        manager.createUser(User.withUsername("user").password(passwordEncoder.encode("123")).authorities("p2").build());
        return manager;
    }*/

    /**
     * 配置加密方式，使用Bcrypt
     * 可使用PasswordEncoderFactories.createDelegatingPasswordEncoder()来指定加密方式
     * 默认bcrypt，可选项有：ldap，MD4，MD5，noop，pbkdf2，scrypt，SHA-1，SHA-256，sha256
     * 需要在密码前加{加密模式}
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * 设置了安全拦截规则
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .authorizeRequests()
                // p/p1需要p1权限
                .antMatchers("/p/p1").hasAuthority("p1")
                // r/r1需要p2权限
                .antMatchers("/r/r2").hasAuthority("p2")
                //其余资源不需要验证，注意有先后顺序，必须放在最后
                .anyRequest().permitAll()
                .and()
                //使用表单登录
                .formLogin()
                //登录成功后跳转页面
                .successForwardUrl("/login‐success")
                .and()
                //使用注销功能
                .logout()
                //注销链接
                .logoutUrl("/logout")
                //注销成功跳转页面
                .logoutSuccessUrl("/login‐view?logout");

        //设置会话
        //默认情况下，Spring Security会为每个登录成功的用户会新建一个Session，就是ifRequired 。
        //always：如果没有session存在就创建一个
        //never：SpringSecurity 将不会创建Session，但是如果应用中其他地方创建了Session，那么Spring Security将会使用它
        //stateless：SpringSecurity将绝对不会创建Session，也不使用Session。这种无状态架构适用于REST API及其无状态认证机制
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
    }


}
